`timescale 1ns/1ns
//behavioral mealy three parallel inputs
module mealy_111_000_bh_case (rst_n, clk, x1, x2, x3, y, z1, z2);
//define inputs and outputs
input rst_n, clk, x1, x2, x3;
output [1:3] y;
output z1, z2;
//variables in always are reg
reg [1:3] y, next_state;

parameter STATE_a = 3'b000,
          STATE_b = 3'b001,
          STATE_c = 3'b011,
          STATE_d = 3'b101,
          STATE_e = 3'b100,
          STATE_f = 3'b010;

// 状态迁移
always @(posedge clk) begin 
    if(rst_n == 1'b0) begin 
        y <= STATE_a;
    end
    else begin 
        y <= next_state;
    end
end

// 次态逻辑
always @(*) begin 
    case(y) 
    STATE_a: 
        if     (~x1 & ~x2 & ~x3) next_state = STATE_b;
        else if( x1 &  x2 &  x3) next_state = STATE_c;
        else                     next_state = STATE_a;
    STATE_b:
        if     (~x1 | ~x2 | ~x3) next_state = STATE_e;
        else                     next_state = STATE_d;
    STATE_c:
        if     ( x1 |  x2 |  x3) next_state = STATE_e;
        else                     next_state = STATE_f;
    STATE_d, STATE_e, STATE_f:
        next_state = STATE_a;
    default: 
        next_state = STATE_a;
    endcase
end

// 输出逻辑
assign z1 = ( (y == STATE_d) && (~x1 & ~x2 & ~x3) ) ? 1'b1 : 1'b0;
assign z2 = ( (y == STATE_f) && ( x1 &  x2 &  x3) ) ? 1'b1 : 1'b0;

endmodule



//test bench for mealy three parallel inputs
module mealy_111_000_bh_case_tb;
//inputs are reg for test bench
//outputs are wire for test bench
reg rst_n, clk, x1, x2, x3;
wire [1:3] y;
wire z1, z2;

//display variables
initial 
    $monitor ("x1 x2 x3 = %b%b%b, state = %b, z1 = %b, z2 = %b", x1, x2, x3, y, z1, z2);

initial begin //define clock 
    clk = 1'b0;
    forever #10 clk = ~clk;
end

//define input sequence
initial begin
    #0 rst_n = 1'b0;
    #5 rst_n = 1'b1;
    #10 x1 = 1'b0;
    x2 = 1'b0;
    x3 = 1'b0;
    //-------------------------------------------
    x1=1'b0;
    x3=1'b1;
    @ (posedge clk) //go to state_a (000)
    x1=1'b1;
    x2=1'b0;
    @ (posedge clk) //go to state_a (000)
    x2=1'b1;
    x3=1'b0;
    @ (posedge clk) //go to state_a (000)
    x1=1'b0;
    x2=1'b0;
    x3=1'b0;
    @ (posedge clk) //go to state_b (001)
    //-------------------------------------------
    x1=1'b1;
    x2=1'b1;
    x3=1'b1;
    @ (posedge clk) //go to state_d (101)
    //-------------------------------------------
    x1=1'b0;
    x2=1'b0;
    x3=1'b0;
    @ (posedge clk) //go to state_a (000), assert z1
    //-------------------------------------------
    x1=1'b1;
    x2=1'b1;
    x3=1'b1;
    @ (posedge clk) //go to state_c (011)
    x1=1'b0;
    x2=1'b0;
    x3=1'b0;
    @ (posedge clk) //go to state_f (010)
    x1=1'b1;
    x2=1'b1;
    x3=1'b1;
    @ (posedge clk) //go to state_a (000), assert z2
    //-------------------------------------------
    x1=1'b1;
    x2=1'b1;
    x3=1'b1;
    @ (posedge clk) //go to state_c (011)
    x1=1'b1;
    x2=1'b0;
    x3=1'b0;
    @ (posedge clk) //go to state_e (100)
    @ (posedge clk)
    //-------------------------------------------
    #20 $finish;
end

//instantiate the module into the test bench
mealy_111_000_bh_case inst1 (rst_n, clk, x1, x2, x3, y, z1, z2);

/*iverilog */
initial begin
    $dumpfile("mealy_111_000_bh_case_tb.vcd"); //生成的 vcd 文件名称
    $dumpvars(0, mealy_111_000_bh_case_tb); //测试模块名称
end

endmodule